﻿
namespace DataCapture.Helper;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using static DataCapture.Helper.PublicHelp;




/// <summary>
/// 表达式树委托(高频数据映射（如实时系统）)
/// </summary>
/// <typeparam name="T"></typeparam>
public  class PropertyAccessor<T> 
{
    private  readonly Dictionary<string, (Func<T, object> Getter, Action<T, object> Setter)> _accessors = new();
   
    private  readonly object _lock = new object();
    private  bool _isInitialized;
   
    public  PropertyAccessor(ElementConfig elementConfig)
    {
        foreach (ModuleConfig moduleConfig in elementConfig.ModuleConfig)
        {
           
            PreCompile(moduleConfig.PartList);
        }
       
    }

    /// <summary>
    /// 预编译方法，需显式调用且线程安全
    /// </summary>
    /// <param name="configParts"></param>
    /// <exception cref="MissingMemberException"></exception>
    private  void PreCompile(List<PublicHelp.PlcPart>  configParts)
    {
        if (_isInitialized)
            return;

        lock (_lock)
        {
            if (!_isInitialized)
            {
               
                //var configParts = ConfigurationSource();
                if (configParts != null && configParts.Count > 0)
                {
                    ValidateConfig(configParts); // 新增配置验证步骤
                    var type = typeof(T);
                    foreach (var part in configParts)
                    {
                        var partType = part.PartType;
                        var property = type.GetProperty(partType);
                        if (property == null)
                            throw new MissingMemberException($"Property '{partType}' not found in {typeof(T).Name}.");

                        var getter = CreateGetter(property);
                        var setter = CreateSetter(property);

                        _accessors[partType] = (getter, setter);
                    }
                }
              
                _isInitialized = true;
            }
        }
    }


    // 新增配置验证方法
    private  void ValidateConfig(List<PublicHelp.PlcPart> configParts)
    {
        // 检查PartType是否唯一
        var partTypes = configParts.Select(p => p.PartType).ToList();
        var duplicates = partTypes.Distinct().Count();
        if (duplicates != partTypes.Count)
        {
            Log4NetHelper.Error($"配置中存在重复的PartType，请确保每个PartType在配置中唯一.{partTypes.Distinct().ToString()}");
            //throw new InvalidOperationException("配置中存在重复的PartType，请确保每个PartType在配置中唯一.");
        }

        // 可在此添加其他验证逻辑，例如检查PartAddress格式
    }

    private  Func<T, object> CreateGetter(PropertyInfo property)
    {
        var param = Expression.Parameter(typeof(T), "data");
        var propExp = Expression.Property(param, property);
        var convert = Expression.Convert(propExp, typeof(object));
        return Expression.Lambda<Func<T, object>>(convert, param).Compile();
    }

    private  Action<T, object> CreateSetter(PropertyInfo property)
    {
        var param = Expression.Parameter(typeof(T), "data");
        var valueParam = Expression.Parameter(typeof(object), "value");
        var castValue = Expression.Convert(valueParam, property.PropertyType);
        var assign = Expression.Assign(Expression.Property(param, property), castValue);
        return Expression.Lambda<Action<T, object>>(assign, param, valueParam).Compile();
    }

    // 安全的属性获取，包含键检查
    public  object GetPropertyValue(T data, string partType)
    {
        if (!_accessors.TryGetValue(partType, out var accessor))
            throw new KeyNotFoundException($"No accessor found for partType '{partType}'.");

        return accessor.Getter(data);
    }

    // 安全的属性设置，包含键检查
    public  void SetPropertyValue(T data, string partType, object value)
    {
        if (!_accessors.TryGetValue(partType, out var accessor))
            throw new KeyNotFoundException($"No accessor found for partType '{partType}'.");

        accessor.Setter(data, value);
    }
    // 根据属性值字典创建并填充对象
    public T CreateObjectWithValues(T data)
    {
        if (!_isInitialized)
            throw new InvalidOperationException("请先调用PreCompile方法初始化配置.");

        T instance = Activator.CreateInstance<T>();
        var propertyValues =_accessors.ToDictionary(
            kvp => kvp.Key,
            kvp => kvp.Value.Getter(data));
        foreach (var kvp in propertyValues)
        {
            if (!_accessors.TryGetValue(kvp.Key, out var accessor))
                throw new KeyNotFoundException($"属性 '{kvp.Key}' 未在配置中找到.");

            // 验证类型是否匹配
            if (kvp.Value.GetType() != accessor.Getter.Method.GetParameters()[1].ParameterType)
                throw new InvalidCastException($"值类型不匹配：属性 '{kvp.Key}' 需要类型 {accessor.Getter.Method.GetParameters()[1].ParameterType.Name}，但传入了 {kvp.Value.GetType().Name}.");

            accessor.Setter(instance, kvp.Value);
        }
        return instance;
    }
}